/******************************************************
Cours:   LOG121
Session: A2013
Groupe:  04
Projet: Laboratoire #4
etudiant(e)s: Fredy Alexander Bonilla, Renaud Vincent, Simon Castro
                            
Professeur : Francis Cardinal
Nom du fichier: CommandeInvoker.java
Date cree: 2013-11-22
Date dern. modif. 2013-11-23
*******************************************************
Historique des modifications
*******************************************************
*Une nouvelle methode privee pour gerer la fabrique des commandes
*La methode ajouterExecuter recoit maintenant un string qui l'envoie a la methode
*privee pour fabriquer une commande
*******************************************************/ 

import java.util.ArrayList;

/**
 * La classe CommandInvoker est le gestionnaire des commandes. Il prepare,
 * memorise et fabrique des commande et les stock dans des arraylist. 
 * 
 * @author Simon
 * @author Fredy
 *
 */
public final class CommandInvoker {
	
	private static CommandInvoker cmd = null;
	private ArrayList<Etat> listeMemento;
	private ArrayList<Command> historique;
	private FabriqueCommande fabrique;
	private int indiceCommande;
	
	/**
	 * Constructeur prive qui previent d'autres classes d'instancier.
	 */
	private CommandInvoker(){
		super();
		this.historique = new ArrayList<Command>();
		this.fabrique = new FabriqueCommande();
		this.listeMemento = new ArrayList<Etat>();
		this.indiceCommande = -1;
	}
	
	/**
	 * Methode retournant l'instance unique de CommandInvoker, selon le patron
	 * Singleton
	 * 
	 * @return cmd une instance unique.
	 */
	public final static CommandInvoker getCommande(){
		
		if(cmd == null){
			cmd = new CommandInvoker();
		}
		
		return cmd;
	}
	
	/**
	 * Methode servant a ajouter une commande dans l'historique pour la stocker.
	 * 
	 * @param commande
	 */
	public void ajouterExecuter(Modifications modifs){
		if(modifs.getOutil() == "zoom" && modifs.getIndice() == -1 &&
				modifs.getPerspective().getPourcentage() == 0){
			// on ne fait rien car l'image est deja reduite au maximum
		}
		else{
			Command commande = this.fabrique.getCommande(modifs);
			this.indiceCommande++;
			this.historique.add(commande);
			commande.execute();
		}
	}
	
	/**
	 * Methode d'ajoute d'un object memento representant le meme etat d'une
	 * perspective dans la liste
	 * 
	 * @param memento
	 */
	public void ajouterMemento(Etat e){
		this.listeMemento.add(e);
	}
	
	/**
	 * Annulation de la modification : UNDO
	 * 
	 * @param p
	 */
	public void annulerModification(Perspective p){
		
		if(this.listeMemento.size() > 0){
			
			int compteur = this.listeMemento.size()-1;
			
			boolean trouve = false;
			
			while(!trouve){
				if(this.listeMemento.get(compteur).getIndex() == p.getIndex())
					trouve = true;
				else
					compteur--;
			}
			
			if(compteur != -1){
				p.restaurer(this.listeMemento.get(compteur).getMemento());
				this.listeMemento.remove(compteur);
			}
		}		
	}
	
	/**
	 * Re-execution d'une commande: REDO
	 */
	public void refaireCommande(){
		
		if(this.indiceCommande != this.historique.size() &&  this.indiceCommande != -1){
			this.historique.get(indiceCommande).execute();
			this.indiceCommande--;
		}
	}
	
	/**
	 * Methode effacant l'historique. Elle est appelee lors du chargement d'une 
	 * sauvegarde.
	 */
	public void reset(){
		this.historique = new ArrayList<Command>();
		this.listeMemento = new ArrayList<Etat>();
		this.indiceCommande = -1;
	}
}
